package com.yonyou.crm.base.product.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.yonyou.crm.base.attrgroup.service.AttrGroupBizServiceImpl;
import com.yonyou.crm.base.brand.service.BrandsBizServiceImpl;
import com.yonyou.crm.base.measure.service.MeasuresBizServiceImpl;
import com.yonyou.crm.base.product.entity.ProductVO;
import com.yonyou.crm.bpub.refervalue.entity.ReferDataVO;
import com.yonyou.crm.common.biz.service.BaseBizServiceImpl;
import com.yonyou.crm.common.enumeration.entity.EnableStateEnum;
import com.yonyou.crm.common.enumeration.service.EnumBizServiceImpl;
import com.yonyou.crm.common.exception.CrmBusinessException;
import com.yonyou.crm.common.field.handler.FieldRelationHandler;
import com.yonyou.crm.common.field.relation.EnumFieldRelation;
import com.yonyou.crm.common.field.relation.FieldRelation;
import com.yonyou.crm.common.field.relation.RefFieldRelation;
import com.yonyou.crm.common.login.context.LoginContextConstant;
import com.yonyou.crm.common.page.entity.Page;
import com.yonyou.crm.common.search.entity.AppSearchPlanEnum;
import com.yonyou.crm.sys.user.entity.TypeEnum;
import com.yonyou.crm.sys.user.service.UserBizServiceImpl;
import com.yonyou.iuap.context.InvocationInfoProxy;

@Service
public class ProductBizServiceImpl extends BaseBizServiceImpl<ProductVO> {

	@Autowired
	private EnumBizServiceImpl enumService;
	@Autowired
	private BrandsBizServiceImpl brandService;
	@Autowired
	private PrdtypeBizServiceImpl prdtypeService;
	@Autowired
	private AttrGroupBizServiceImpl agService;
	@Autowired
	private MeasuresBizServiceImpl measureService;
	@Autowired
	private ProductOrgBizServiceImpl poService;
	@Autowired
	private SaleUnitBizServiceImpl suService;
	@Autowired
	private UserBizServiceImpl userService;
	
	/**
	 * 查询产品列表
	 * @param page
	 * @param paraMap
	 * @return
	 */
	public Page<ProductVO> getPage(Page<ProductVO> page, Map<String, Object> paraMap) {
		
		Page<ProductVO> rPage = null;
		if (paraMap == null) {
			paraMap = new HashMap<String, Object>();
		}
		
		paraMap.put("tenantId", InvocationInfoProxy.getTenantid());

		//非管理员角色，只能查看自己公司的产品
		int userType = userService.getUserTypeById(new Long(InvocationInfoProxy.getParameter(LoginContextConstant.UserId)));
		if (userType == TypeEnum.USER.getValue()) {
			paraMap.put("orgId", new Long(InvocationInfoProxy.getParameter(LoginContextConstant.OrgId)));
		}
		
		//全部、我关注
		if ((paraMap.containsKey("option")) && (paraMap.get("option") != null)) {
			
			int option = (int)paraMap.get("option");
			String optionSql = "";
			if (option == AppSearchPlanEnum.FOLLOW.getValue()) {
				optionSql = " and prd.id in (select product_id from base_product_follow where user_id = "+InvocationInfoProxy.getParameter(LoginContextConstant.UserId)+")";
				paraMap.put("option", optionSql);
			}
		}
		
		rPage = super.pageSelect(ProductVO.class, page, paraMap.keySet().toArray(new String[0]), paraMap.values().toArray(new Object[0]));
		
		trans(rPage.getData());
		
		return rPage;
	}
	
	/**
	 * 产品详情
	 * @param code
	 * @return
	 */
	public ProductVO getDetail(Long id) {
		
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("ownerId", new Long(InvocationInfoProxy.getParameter("id")));
		paramMap.put("id", id);
				
		ProductVO pVO = (ProductVO) dao.selectOne(ProductVO.class, "getProductById", paramMap);
		
		if (pVO != null) {
			trans(Arrays.asList(pVO));
		}
		
		//销售单位
		pVO.setSaleUnits(suService.getSUListByPrdId(id));
		
		//属性
		pVO.setAttrList(agService.getAttrListByAGId(pVO.getAttrGroupId()));
		
		return pVO;
	}
	
	@Override
	protected void beforeSaveVO(ProductVO vo) {		
		
		//校验编码唯一性
		String code = vo.getCode();
		String name = vo.getName();
		int codeCount = getCountByCode(vo.getId(), code);
		if (codeCount > 0) {
			throw new CrmBusinessException("编码和其他产品重复，保存失败。");
		}
		
		//校验名称唯一性
		int nameCount = getCountByName(vo.getId(), name);
		if (nameCount > 0) {
			throw new CrmBusinessException("名称和其他产品重复，保存失败。");
		}
		
		super.beforeSaveVO(vo);
		
		vo.setEnableState(EnableStateEnum.ENABLE.getValue());
	}
	
	@Override
	protected void afterSaveVO(ProductVO vo) {
		
		suService.insertSaleUnit(vo);
		
		trans(Arrays.asList(vo));
	}

	@Override
	protected void beforeUpdateVO(ProductVO vo) {
		
		//校验编码唯一性
		String code = vo.getCode();
		String name = vo.getName();
		int codeCount = getCountByCode(vo.getId(), code);
		if (codeCount > 0) {
			throw new CrmBusinessException("编码和其他产品重复，保存失败。");
		}
		
		//校验名称唯一性
		int nameCount = getCountByName(vo.getId(), name);
		if (nameCount > 0) {
			throw new CrmBusinessException("名称和其他产品重复，保存失败。");
		}
		
		super.beforeUpdateVO(vo);
	}

	@Override
	protected void afterUpdateVO(ProductVO vo) {
		super.afterUpdateVO(vo);
		
		suService.updateSaleUnit(vo);
		
		trans(Arrays.asList(vo));
	}

	/**
	 * 批量删除
	 * @param ids
	 */
	public String batchDelete(String[] ids) {

		if (ids == null || ids.length == 0) {
			return "";
		}
		
		Set<String> idSet = new HashSet<String>();
		for (String id : ids) {
			idSet.add(id);
		}
		
		int totalCount = idSet.size();
		
		StringBuffer reasonBuffer = new StringBuffer("【");
		
		//是否被业务对象引用
		List<Map<String, Object>> productList = getProductByBObj(idSet.toArray(new String[0]));
		
		if (productList != null && productList.size() > 0) {
			
			for (Map<String, Object> map : productList) {
				
				reasonBuffer.append(map.get("name"));
				reasonBuffer.append(",");

				String typeId = map.get("id").toString();
				//被业务对象引用不能删除
				idSet.remove(typeId);
			}
			reasonBuffer.delete(reasonBuffer.length()-1, reasonBuffer.length());
			reasonBuffer.append("】产品已被引用，不可删除！");
		}
		
		int successCount = idSet.size();
		int failCount = totalCount - idSet.size();
		String message = failCount == 0 ? "成功" + successCount + "条。" : "成功" + successCount + "条，失败" + failCount + "条。\n失败原因：" + reasonBuffer.toString();
		
		if (successCount > 0) {
			
			//删除产品
			super.batchDeleteByIDs(ProductVO.class, idSet.toArray(new String[0]));
			//删除产品组织
			poService.batchDeleteProductOrg(idSet.toArray(new String[0]));
			//删除销售单位
			suService.batchDeleteSaleUnit(idSet.toArray(new String[0]));
		}
		
		return message;
	}
	
	/**
	 * 批量停启用
	 * @param codes
	 * @param enableState
	 */
	public void batchUpdateEnableState(String[] ids, Integer enableState) {
		
		if (ids == null || ids.length == 0) {
			return;
		}
		
		Map<String, Object> paraMap = new HashMap<String, Object>();
		paraMap.put("ids", ids);
		paraMap.put("enableState", enableState);
		if (enableState.intValue() == EnableStateEnum.ENABLE.getValue()) {
			paraMap.put("enableUserId", new Long(InvocationInfoProxy.getParameter("id")));
			paraMap.put("enableTime", new Date());
		}
		else {
			paraMap.put("disableUserId", new Long(InvocationInfoProxy.getParameter("id")));
			paraMap.put("disableTime", new Date());	
		}
		
		dao.updateSql(ProductVO.class, "batchUpdateEnableState", paraMap);
	}
	
	/**
	 * 根据编码查询产品数量
	 * @param id
	 * @param code
	 * @return
	 */
	public int getCountByCode(Long id, String code) {
		
		Map<String, Object> paraMap = new HashMap<String, Object>();
		paraMap.put("id", id);
		paraMap.put("code", code);
		paraMap.put("tenantId", new Long(InvocationInfoProxy.getTenantid()));
		return dao.countAll(ProductVO.class, "getCountByCode", paraMap);
	}
	
	/**
	 * 根据名称查询产品数量
	 * @param id
	 * @param name
	 * @return
	 */
	public int getCountByName(Long id, String name) {
		
		Map<String, Object> paraMap = new HashMap<String, Object>();
		paraMap.put("id", id);
		paraMap.put("name", name);
		paraMap.put("tenantId", new Long(InvocationInfoProxy.getTenantid()));
		return dao.countAll(ProductVO.class, "getCountByName", paraMap);
	}
	
	/**
	 * 关注产品
	 * @param code
	 * @return
	 */
	public int saveProductFollow(Long id) {
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("productId", id);
		param.put("userId", InvocationInfoProxy.getParameter("id"));
		int count = dao.countAll(ProductVO.class, "countFollow", param);
		if (count > 0) {
			return 1;
		}
		return dao.saveSql(ProductVO.class, "insertProductFollow", param);
	}
	
	/**
	 * 删除产品关注
	 * @param code
	 * @return
	 */
	public int deleteProductFollow(Long id) {
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("productId", id);
		param.put("userId", InvocationInfoProxy.getParameter("id"));
		return dao.deleteSql(ProductVO.class, "deleteProductFollow", param);
	}
	
	/*
	 * 获取参照档案列表
	 */
	public List<ReferDataVO> getRefervalues(Page<ProductVO> page, Map<String, Object> paraMap) {
		// TODO 加权限
		// 产品参照档案，返回产品名称，分类，品牌，销售单价
		Page<ProductVO> pageVO = dao.pageSelect(ProductVO.class, page, "selectRefervalues", "countRefervalues", paraMap);
		trans(pageVO.getData());
		
		List<ProductVO> voList = pageVO.getData();
		
		List<ReferDataVO> rsList = new ArrayList<ReferDataVO>();
		for (ProductVO vo : voList) {
			ReferDataVO referDataVO = new ReferDataVO();
			referDataVO.setId(vo.getId().toString());
			referDataVO.setValue(vo.getName());
			
			rsList.add(referDataVO);
		}
		return rsList;
	}
	
	/*
	 * 获取参照档案列表
	 */
	public List<ProductVO> getRefervaluesForApp(Page<ProductVO> page, Map<String, Object> paraMap) {
		// TODO 加权限
		// 产品参照档案，返回产品名称，分类，品牌，销售单价
		Page<ProductVO> pageVO = dao.pageSelect(ProductVO.class, page, "selectRefervalues", "countRefervalues", paraMap);
		List<ProductVO> voList = pageVO.getData();
		trans(voList);
		return voList;
	}
	
	/**
	 * 是否被业务对象引用
	 * @param id
	 * @return
	 */
	public boolean isCitedByBObj(Long id) {
		List<Map<String, Object>> objList = getProductByBObj(new String[]{id.toString()});
		return objList != null && objList.size() > 0;
	}
	
	/**
	 * 校验产品是否被业务对象引用
	 * @param ids
	 * @return
	 */
	public List<Map<String, Object>> getProductByBObj(String[] ids) {
		if (ids == null || ids.length == 0) {
			return null;
		}
		return dao.selectList(ProductVO.class, "getProductByBObj", ids);
	}
	
	/**
	 * 分页参照列表
	 * @param page
	 * @param paraMap
	 * @return
	 */
	public Page<ProductVO> getRefPage(Page<ProductVO> page, Map<String, Object> paraMap) {

		if (paraMap == null) {
			paraMap = new HashMap<String, Object>();
		}
		
		paraMap.put("tenantId", new Long(InvocationInfoProxy.getTenantid()));
		paraMap.put("orgId", new Long(InvocationInfoProxy.getParameter(LoginContextConstant.OrgId)));
		
		Page<ProductVO> rPage = dao.pageSelect(ProductVO.class, page, "getRefPage", "countRefPage", paraMap);
		
		trans(rPage.getData());
		
		return rPage;
	}
	
	/**
	 * 无分页参照列表
	 * @param paraMap
	 * @return
	 */
	public List<ProductVO> getRefList(Map<String, Object> paraMap) {

		if (paraMap == null) {
			paraMap = new HashMap<String, Object>();
		}
		
		paraMap.put("tenantId", new Long(InvocationInfoProxy.getTenantid()));
		paraMap.put("orgId", new Long(InvocationInfoProxy.getParameter(LoginContextConstant.OrgId)));
		
		return dao.selectVoList(ProductVO.class, "getRefList", paraMap);
	}
	
	private List<ProductVO> trans(List<ProductVO> productList) {
		
		if (productList != null && productList.size() > 0) {
			
			List<FieldRelation<ProductVO>> relations = new ArrayList<FieldRelation<ProductVO>>();
			relations.add(new RefFieldRelation<ProductVO>(ProductVO.class, "id", new String[]{"orgId","orgName"}, poService, "selectProductOrgById"));
			relations.add(new RefFieldRelation<ProductVO>(ProductVO.class, "id", new String[]{"saleUnitName"}, suService, "selectSaleUnitById"));
			relations.add(new EnumFieldRelation<ProductVO>(ProductVO.class, "enableState", "enableStateName", enumService, "enable_state"));
			relations.add(new RefFieldRelation<ProductVO>(ProductVO.class, "prdtypeId", new String[]{"prdtypeName"}, prdtypeService, "selectFieldsByIds"));
			relations.add(new RefFieldRelation<ProductVO>(ProductVO.class, "brandId", new String[]{"brandName"}, brandService, "selectFieldsByIds"));
			relations.add(new RefFieldRelation<ProductVO>(ProductVO.class, "attrGroupId", new String[]{"attrGroupName"}, agService, "selectFieldsByIds"));
			relations.add(new RefFieldRelation<ProductVO>(ProductVO.class, "measureId", new String[]{"measureName"}, measureService, "selectFieldsByIds"));
			
			new FieldRelationHandler<ProductVO>().handler(productList, relations);
		}

		return productList;
	}

}
